#include <iostream>
using namespace std;
#include <string>

// 1：类型模板参数
//  template<class T>
//  class A{

// };

// 2:非类型模板参数
//  一般是使用整形
// template <class T, int N>
// class A
// {
// private:
//     T _arr[N];
// };

// int m1()
// {
//     A<int, 100> a1;  // 100
//     A<int, 1000> a2; // 1000
//     return 0;
// }

#include <string.h>
// 3:模板的特化
template <class T>
bool isequal(T &left, T &right)
{
    return left == right;
}

// 如果是char*类型的数据，那么调用这个函数就会来到这里
template <>
bool isequal<char *>(char *&left, char *&right)
{
    return strcmp(left, right);
}

int m2()
{
    int x = 1;
    int y = 2;
    cout << isequal(x, y) << endl;

    string str1 = "aello";
    string str2 = "world";
    cout << isequal(str1, str2) << endl;
    return 0;
}

// 3:类模板特化
template <class T, class T2>
class date
{
public:
    date()
    {
        cout << "普通特化" << endl;
    }

private:
    T _a;
    T2 _b;
};

template <>
class date<int, char>
{
public:
    date()
    {
        cout << "偏特化" << endl;
    }

private:
};

template <class T2>
class date<int, T2>
{
public:
    date()
    {
        cout << "date<int, T2>特化" << endl;
    }

private:
};

template <class T1, class T2>
class date<T1 *, T2 *>
{
public:
    date()
    {
        cout << " date<T1*,T2*>特化" << endl;
    }

private:
};
template <class T1, class T2>
class date<T1 &, T2 &>
{
public:
    date()
    {
        cout << " date<T1&,T2&>特化" << endl;
    }

private:
};

int m3()
{
    date<char, int> d1;
    date<int, char> d2;
    date<int, float> d3;
    date<char *, char *> d4;
    date<char &, char &> d5;

    return 0;
}




//继承
class Person
{
public:
    Person(const string &name, const string &sex, const int age) : _name(name), _sex(sex), _age(age)
    {
    }
    void print(){
        cout<<_name<<"-"<<_sex<<"-"<<_age<<endl;
    }

protected:
    string _name;
    string _sex;
    int _age;
};
class student : public Person
{
public:
    student(const string &name, const string &sex, const int age,const int id):Person(name,sex,age),_id(id)
    {

    }

    //这里进行基类的初始化的时候，可以直接穿子类进去完成基类的构造函数
    student(const student& s):Person(s),_id(s._id){
    }

    //赋值:不用初始化
    //这个也是一个默认成员函数
    student& operator=(const student& s){
        if(this != &s){
            //这里会发生跨界的错误，因为基类也有默认的赋值，然后我们这里
            //有2个赋值，就会被重定义了。所以不能要去调用基类的赋值
            Person::operator=(s);
            _id = s._id;
            cout<<" student& operator=(const student& s)"<<endl;
        }
        return *this;
    }
    void print(){
        cout<<_name<<"-"<<_sex<<"-"<<_age<<"-"<<_id<<endl;
    }
private:
    int _id;
};

int main()
{
    Person p1("张3","男",21);
    student s1("李四","男",22,2022);
    student s2("王5","男",23,2024);

    s2 = s1;
    s2.print();


    // //p1 = s1;//切片
    // Person* p2 = &s1;//指针赋值
    // Person& p3 = s1;//引用赋值

    // //一般情况下，基类不能赋值给派生类，但是前面基类保存了派生类的地址，这样就可以通过强转进行赋值
    // student* sptr = (student*)p2;

    
    
    return 0;
}